home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / ptv1n2.arc / SEARCH.C < prev    next >
Text File  |  1990-06-14  |  7KB  |  172 lines

  1. /*
  2.  * Program to search the file specified by the first command-line
  3.  * argument for the string specified by the second command-line
  4.  * argument. Performs the search by reading and searching blocks
  5.  * of size BLOCK_SIZE.
  6.  */
  7. #include <stdio.h>
  8. #include <fcntl.h>
  9. #include <string.h>
  10. #include <alloc.h>   /* alloc.h for Turbo C 2.0,
  11.                         malloc.h for Microsoft C 5.0 */
  12.  
  13. #define BLOCK_SIZE  0x4000   /* we'll process the file in 16Kb
  14.                                  blocks */
  15.  
  16. /* Searches the specified number of sequences in the specified buffer
  17.    for matches to SearchString of SearchStringLength. Note that the
  18.    calling code should already have shortened SearchLength if
  19.    necessary to compensate for the distance from the end of the buffer
  20.    to the last possible start of a matching sequence in the buffer */
  21. int SearchForString(unsigned char *Buffer, int SearchLength,
  22.    unsigned char *SearchString, int SearchStringLength)
  23. {
  24.    unsigned char *PotentialMatch;
  25.  
  26.    /* Search so long as there are potential-match locations
  27.       remaining */
  28.    while ( SearchLength ) {
  29.       /* See if the first character of SearchString can be found */
  30.       if ( (PotentialMatch =
  31.             memchr(Buffer, *SearchString, SearchLength)) == NULL ) {
  32.          break;   /* no matches in this buffer */
  33.       }
  34.  
  35.       /* The first character matches; see if the rest of the string
  36.          also matches */
  37.       if ( SearchStringLength == 1 ) {
  38.          return(1);  /* that 1 matching character was the whole
  39.                         search string, so we've got a match */
  40.       } else {
  41.          /* Check whether the remaining characters match */
  42.          if ( !memcmp(PotentialMatch + 1, SearchString + 1,
  43.                SearchStringLength - 1) ) {
  44.             return(1);  /* we've got a match */
  45.          }
  46.       }
  47.  
  48.       /* The string doesn't match; keep going by pointing past the
  49.          potential-match location we just rejected */
  50.       SearchLength -= PotentialMatch - Buffer + 1;
  51.       Buffer = PotentialMatch + 1;
  52.    }
  53.  
  54.    return(0);  /* no match found */
  55. }
  56.  
  57. main(int argc, char *argv[]) {
  58.    int Done;               /* indicates whether search is done */
  59.    int Handle;             /* handle of file being searched */
  60.    int WorkingLength;      /* length of current block */
  61.    int SearchStringLength; /* length of string to search for */
  62.    int BlockSearchLength;  /* length to search in current block */
  63.    int Found;              /* indicates final search completion
  64.                               status */
  65.    int NextLoadCount;      /* # of bytes to read into next block,
  66.                               accounting for bytes copied from the last
  67.                               block */
  68.    unsigned char *WorkingBlock;  /* block storage buffer */
  69.    unsigned char *SearchString;  /* pointer to string to search for */
  70.    unsigned char *NextLoadPtr;   /* offset at which to start loading
  71.                                     the next block, accounting for
  72.                                     bytes copied from the last
  73.                                     block */
  74.  
  75.    /* Check for the proper number of arguments */
  76.    if ( argc != 3 ) {
  77.       printf("usage: search filename search-string\n");
  78.       exit(1);
  79.    }
  80.  
  81.    /* Try to open the file to be searched */
  82.    if ( (Handle = open(argv[1], O_RDONLY | O_BINARY)) == -1 ) {
  83.       printf("Can't open file: %s\n", argv[1]);
  84.       exit(1);
  85.    }
  86.  
  87.    /* Calculate the length of text to search for */
  88.    SearchString = argv[2];
  89.    SearchStringLength = strlen(SearchString);
  90.  
  91.    /* Try to get memory in which to buffer the data */
  92.    if ( (WorkingBlock = malloc(BLOCK_SIZE)) == NULL ) {
  93.       printf("Can't get enough memory\n");
  94.       exit(1);
  95.    }
  96.  
  97.    /* Load the first block at the start of the buffer, and try to fill
  98.       the entire buffer */
  99.    NextLoadPtr = WorkingBlock;
  100.    NextLoadCount = BLOCK_SIZE;
  101.  
  102.    Done = 0;      /* not done with search yet */
  103.    Found = 0;     /* assume we won't find a match */
  104.  
  105.    /* Search the file in BLOCK_SIZE chunks */
  106.    do {
  107.       /* Read in however many bytes are needed to fill out the block
  108.          (accounting for bytes copied over from the last block), or
  109.          the rest of the bytes in the file, whichever is less */
  110.       if ( (WorkingLength = read(Handle, NextLoadPtr,
  111.             NextLoadCount)) == -1 ) {
  112.          printf("Error reading file %s\n", argv[1]);
  113.          exit(1);
  114.       }
  115.  
  116.       /* If we didn't read all the bytes we requested, we're done
  117.          after this block whether we find a match or not */
  118.       if ( WorkingLength != NextLoadCount ) {
  119.          Done = 1;
  120.       }
  121.  
  122.       /* Account for any bytes we copied from the end of the last
  123.          block in the total length of this block */
  124.       WorkingLength += NextLoadPtr - WorkingBlock;
  125.  
  126.       /* Calculate the number of bytes in this block that could
  127.          possibly be the start of a matching sequence that lies
  128.          entirely in this block (sequences that run off the end of the
  129.          block will be transferred to the next block and found when
  130.          that block is searched) */
  131.       if ( (BlockSearchLength =
  132.                WorkingLength - SearchStringLength + 1) <= 0 ) {
  133.             Done = 1;   /* too few characters in this block for there
  134.                         to be any possible matches, so this is the
  135.                         final block and we're done without finding a
  136.                         match */
  137.       } else {
  138.          /* Search this block */
  139.          if ( SearchForString(WorkingBlock, BlockSearchLength,
  140.                SearchString, SearchStringLength) ) {
  141.             Found = 1;     /* we've found a match */
  142.             Done = 1;
  143.          } else {
  144.             /* Copy any bytes from the end of the block that start
  145.                potentially-matching sequences that would run off the
  146.                end of the block over to the next block */
  147.             if ( SearchStringLength > 1 ) {
  148.                memcpy(WorkingBlock,
  149.                   WorkingBlock + BLOCK_SIZE - SearchStringLength + 1,
  150.                   SearchStringLength - 1);
  151.             }
  152.  
  153.             /* Set up to load the next bytes from the file after the
  154.                bytes copied from the end of the current block */
  155.             NextLoadPtr = WorkingBlock + SearchStringLength - 1;
  156.             NextLoadCount = BLOCK_SIZE - SearchStringLength + 1;
  157.          }
  158.       }
  159.    } while ( !Done );
  160.  
  161.    /* Report the results */
  162.    if ( Found ) {
  163.       printf("String found\n");
  164.    } else {
  165.       printf("String not found\n");
  166.    }
  167.  
  168.    exit(Found);   /* return the found/not found status as the
  169.                      DOS errorlevel */
  170. }
  171.  
  172.